#pragma once
#include "index_buffer.h"

namespace krryn{
namespace system_imp{
	class index_buffer_opengl : public view::index_buffer{
	public:
		index_buffer_opengl(size_t a_NumberOfIndices, view::index_buffer_format a_Format)
			: index_buffer(a_NumberOfIndices, a_Format)
		{
			glGenBuffersARB(1, &m_BufferId);
			glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_BufferId);
			glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, get_size_in_bytes(), 0, GL_STATIC_DRAW_ARB);
		}

		virtual ~index_buffer_opengl(){
			glDeleteBuffersARB(1, &m_BufferId);
		}

		virtual void write_data(size_t a_OffsetInBytes, size_t a_SizeInBytes, const void *a_Source){
			glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_BufferId);
			glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, a_OffsetInBytes, a_SizeInBytes, a_Source);
		}

		virtual void read_data(size_t a_OffsetInBytes, size_t a_SizeInBytes, void *a_Destination){
			glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_BufferId);
			glGetBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, a_OffsetInBytes, a_SizeInBytes, a_Destination);
		}

		GLuint get_buffer_id() const { return m_BufferId; }
	protected:
		virtual void* lock_impl(){
			GLenum l_Mode = -1;

			if(locked() == read)			l_Mode = GL_READ_ONLY_ARB;
			else if(locked() == write)		l_Mode = GL_WRITE_ONLY_ARB;
			else if(locked() == read_write)	l_Mode = GL_READ_WRITE_ARB;

			glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_BufferId);
			return glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, l_Mode);
		}

		virtual void unlock_impl(){
			glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_BufferId);
			glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
		}
	private:
		GLuint m_BufferId;
	};
}
}